package com.zhouxl.program.multi;

import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author zhouxl
 * @DATE 2021/7/11
 * @descriptoin
 */
@Component
public class RedisMulti {

    @Autowired
    private RedisTemplate redisTemplate;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public void multi(){
        // 出现了异常，Caused by: io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI
        // 原因是：spring集成redis，对于redis的事务默认不开启
        redisTemplate.multi();
        ValueOperations setOpr = redisTemplate.opsForValue();
        logger.info(setOpr.increment("mykey")+"");
        logger.info(setOpr.increment("mykey")+"");
        redisTemplate.exec();
    }


    public void openMulti(){
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.multi();
        try{
            redisTemplate.opsForValue().increment("mykey");
            redisTemplate.opsForValue().increment("mykey");
            redisTemplate.exec();
        }catch (Exception ex){
            redisTemplate.discard();
        }
    }

    public void openMultiRollback(){
//        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.execute(new SessionCallback<List<Object>>() {
            @Override
            public List<Object> execute(RedisOperations operations) throws DataAccessException {
                operations.watch("mykey");
                redisTemplate.multi();
                redisTemplate.opsForValue().increment("mykey");
                redisTemplate.opsForValue().increment("mykey");
                return operations.exec();
            }
        });
    }


    public void threadWatchResult(){
        final int THREAD_NUM = 5;
        for(int i=0 ; i<THREAD_NUM; i++){
            new Thread(()->{
                Object execute = redisTemplate.execute(new SessionCallback<List<Object>>() {
                    @SneakyThrows
                    @Override
                    public List<Object> execute(RedisOperations operations) throws DataAccessException {
                        operations.watch("mykey");
                        redisTemplate.multi();
                        redisTemplate.opsForValue().increment("mykey");
                        redisTemplate.opsForValue().increment("mykey");
                        Thread.sleep(1000);
                        return operations.exec();
                    }
                });
                logger.info("----"+execute.toString());
            }).start();
        }
    }

}
